home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 1 / Amiga Tools.iso / disk-tools / cd-tools / amicdrom / devsupp.c < prev    next >
C/C++ Source or Header  |  1994-06-06  |  14KB  |  513 lines

  1. /* devsupp.c:
  2.  *
  3.  * Support routines for the device handler.
  4.  * - debugging
  5.  * - Mountlist "Startup" field parsing
  6.  *
  7.  * ----------------------------------------------------------------------
  8.  * This code is (C) Copyright 1993,1994 by Frank Munkert.
  9.  * All rights reserved.
  10.  * This software may be freely distributed and redistributed for
  11.  * non-commercial purposes, provided this notice is included.
  12.  * ----------------------------------------------------------------------
  13.  * History:
  14.  * 
  15.  * 09-Apr-94   fmu   Larger buffer for startup strings.
  16.  * 02-Jan-94   fmu   New options XPOS and YPOS.
  17.  * 11-Dec-93   fmu   Memory type can now be chosen by the user:
  18.  *                   new options CHIP, DMA and ANY.
  19.  * 11-Dec-93   fmu   The assembly code stubs for the debugging process
  20.  *                   are no longer necessary; the debugger code is now
  21.  *                   called with CreateNewProcTags().
  22.  * 21-Nov-93   fmu   New option SCANINTERVAL.
  23.  * 14-Nov-93   fmu   Added Handle_Control_Packet for 'cdcontrol' program.
  24.  * 10-Nov-93   fmu   New options SHOWVERSION and HFSFIRST.
  25.  * 23-Oct-93   fmu   MacHFS options added.
  26.  * 15-Oct-93   fmu   Adapted to new VOLUME structure.
  27.  */
  28.  
  29. /*
  30.  * Extract information from Mountlist "Startup" field.
  31.  */
  32.  
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <stdarg.h>
  36. #include <stdio.h>
  37.  
  38. #ifdef _DCC
  39. #define abs
  40. #endif
  41.  
  42. #include <exec/types.h>
  43. #include <dos/dostags.h>
  44. #include <clib/dos_protos.h>
  45. #include "device.h"
  46. #include "devsupp.h"
  47. #include "intui.h"
  48. #include "params.h"
  49. #include "cdcontrol.h"
  50.  
  51. static char *TheVersion = "$VER: " VERSION;
  52.  
  53. unsigned long g_memory_type;
  54.  
  55. int
  56. Get_Startup (LONG p_startup)
  57. {
  58.   enum {
  59.     ARG_DEVICE,
  60.     ARG_UNIT,
  61.     ARG_CHIP,
  62.     ARG_FAST,
  63.     ARG_DMA,
  64.     ARG_ANY,
  65.     ARG_LOWERCASE,
  66.     ARG_ROCKRIDGE,
  67.     ARG_TRACKDISK,
  68.     ARG_MACTOISO,
  69.     ARG_CONVERTSPACES,
  70.     ARG_SHOWVERSION,
  71.     ARG_HFSFIRST,
  72.     ARG_STDBUFFERS,
  73.     ARG_FILEBUFFERS,
  74.     ARG_DATAEXT,
  75.     ARG_RESOURCEEXT,
  76.     ARG_SCANINTERVAL,
  77.     ARG_PLAYCDDA,
  78.     ARG_XPOS,
  79.     ARG_YPOS,
  80.     ARGCOUNT
  81.   };
  82.  
  83.   STRPTR Args[ARGCOUNT],Index;
  84.   UBYTE LocalBuffer[250];
  85.   struct RDArgs *ArgsPtr;
  86.   int result = FALSE,len,i;
  87.   int cnt;
  88.  
  89.   /* Clear the argument vector. */
  90.   memset (Args, 0, sizeof(Args));
  91.  
  92.   /* valid startup entry? */
  93.   if (!p_startup) {
  94.     Display_Error ("Filesystem startup entry invalid");
  95.     return FALSE;
  96.   }
  97.  
  98.   /* Get the contents of the startup field. */
  99.   len = ((STRPTR)(BADDR(p_startup)))[0];
  100.   if (len > sizeof (LocalBuffer) - 1)
  101.     len = sizeof (LocalBuffer) - 1;
  102.   memcpy (LocalBuffer, ((STRPTR)(BADDR(p_startup))) + 1, len);
  103.  
  104.   /* Provide null-termination. */
  105.   LocalBuffer[len] = 0;
  106.  
  107.   /* Remove leading quotes. */
  108.   for (i = 0 ; i < len ; i++) {
  109.     if (LocalBuffer[i] != ' ') {
  110.       if (LocalBuffer[i] == '\"')
  111.     LocalBuffer[i] = ' ';
  112.       break;
  113.     }
  114.   }
  115.  
  116.   /* Remove trailing quotes. */
  117.   for (i = len - 1 ; i >= 0 ; i--) {
  118.     if (LocalBuffer[i] != ' '){
  119.       if (LocalBuffer[i] == '\"')
  120.     LocalBuffer[i] = ' ';
  121.       break;
  122.     }
  123.   }
  124.  
  125.   /* Replace "-" by spaces, except "--" which is replaced by "-". */
  126.   Index = LocalBuffer;
  127.   for (i = 0 ; i < len ; i++) {
  128.     if (LocalBuffer[i] == '-') {
  129.       if (i+1 < len && LocalBuffer[i+1] == '-') {
  130.         *Index++ = '-';
  131.     i++;
  132.       } else
  133.         *Index++ = ' ';
  134.     } else
  135.       *Index++ = LocalBuffer[i];
  136.   }
  137.  
  138.   /* Provide null-termination. */
  139.   *Index = 0;
  140.  
  141.   /* Don't forget the newline, or ReadArgs won't work. */
  142.   strcat ((char *) LocalBuffer, "\n");
  143.  
  144.   if (ArgsPtr = (struct RDArgs *) AllocDosObjectTags (DOS_RDARGS,TAG_DONE)) {
  145.  
  146.     /* Don't prompt for input! */
  147.     ArgsPtr -> RDA_Flags |= RDAF_NOPROMPT;
  148.  
  149.     /* Set up for local parsing. */
  150.     ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
  151.     ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
  152.     ArgsPtr->RDA_Source.CS_CurChr = 0;
  153.  
  154.     /* Read the arguments. */
  155.     if (ReadArgs ((UBYTE *)
  156.                 "D=DEVICE,U=UNIT/N,C=CHIP/S,F=FAST/S,DMA/S,ANY/S,"
  157.           "L=LOWERCASE/S,"
  158.              "R=ROCKRIDGE/S,T=TRACKDISK/S,"
  159.           "MI=MACTOISO/S,CS=CONVERTSPACES/S,"
  160.           "SV=SHOWVERSION/S,HF=HFSFIRST/S,"
  161.           "SB=STDBUFFERS/K/N,FB=FILEBUFFERS/K/N,"
  162.           "DE=DATAEXT/K,RE=RESOURCEEXT/K,"
  163.           "SI=SCANINTERVAL/K/N,PC=PLAYCDDA/K,"
  164.           "X=XPOS/K/N,Y=YPOS/K/N",
  165.           (LONG *) Args, ArgsPtr)) {
  166.       result = TRUE;
  167.  
  168.       if (Args[ARG_DEVICE]) {
  169.         len = strlen((char *) (Args[ARG_DEVICE]));
  170.  
  171.         if (len >= sizeof (g_device)) {
  172.        Display_Error ("Device name entry too long");
  173.        result = FALSE;
  174.         } else
  175.       strcpy (g_device, (char *) (Args[ARG_DEVICE]));
  176.       } else
  177.         Display_Error("Device name entry missing");
  178.  
  179.       g_unit = *(long *) (Args[ARG_UNIT]);
  180.  
  181.       g_memory_type = MEMF_CHIP;
  182.       cnt = 0;
  183.       if (Args[ARG_FAST] != NULL) {
  184.         g_memory_type = MEMF_FAST;
  185.     cnt++;
  186.       }
  187.       if (Args[ARG_CHIP] != NULL) {
  188.         g_memory_type = MEMF_CHIP;
  189.     cnt++;
  190.       }
  191.       if (Args[ARG_DMA] != NULL) {
  192.         g_memory_type = MEMF_24BITDMA;
  193.     cnt++;
  194.       }
  195.       if (Args[ARG_ANY] != NULL) {
  196.         g_memory_type = MEMF_ANY;
  197.     cnt++;
  198.       }
  199.       if (cnt > 1) {
  200.         Display_Error ("Only ONE memory option may be used!");
  201.     result = FALSE;
  202.       }
  203.  
  204.       g_map_to_lowercase = (Args[ARG_LOWERCASE] != NULL);
  205.       g_use_rock_ridge = (Args[ARG_ROCKRIDGE] != NULL);
  206.       g_trackdisk = (Args[ARG_TRACKDISK] != NULL);
  207.       g_show_version_numbers = (Args[ARG_SHOWVERSION] != NULL);
  208.       g_hfs_first = (Args[ARG_HFSFIRST] != NULL);
  209.  
  210.       if (Args[ARG_STDBUFFERS]) {      
  211.         g_std_buffers = *(long *) (Args[ARG_STDBUFFERS]);
  212.         if (g_std_buffers <= 0) {
  213.           Display_Error ("Illegal number of standard buffers: %ld", g_std_buffers);
  214.       result = FALSE;
  215.         }
  216.       } else
  217.         g_std_buffers = 5;
  218.       
  219.       if (Args[ARG_FILEBUFFERS]) {
  220.         g_file_buffers = *(long *) (Args[ARG_FILEBUFFERS]);
  221.         if (g_file_buffers <= 0) {
  222.           Display_Error ("Illegal number of file buffers: %ld", g_std_buffers);
  223.       result = FALSE;
  224.         }
  225.       } else
  226.         g_file_buffers = 5;
  227.  
  228.       if (Args[ARG_DATAEXT])
  229.         strcpy (g_data_fork_extension, (char *) Args[ARG_DATAEXT]);
  230.  
  231.       if (Args[ARG_RESOURCEEXT])
  232.         strcpy (g_resource_fork_extension, (char *) Args[ARG_RESOURCEEXT]);
  233.  
  234.       g_convert_hfs_filenames = (Args[ARG_MACTOISO] != NULL);
  235.       g_convert_hfs_spaces = (Args[ARG_CONVERTSPACES] != NULL);
  236.  
  237.       if (Args[ARG_SCANINTERVAL]) {
  238.         g_scan_interval = *(long *) (Args[ARG_SCANINTERVAL]);
  239.         if (g_scan_interval < 0)
  240.           g_scan_interval = 0;
  241.       } else
  242.         g_scan_interval = 3;
  243.  
  244.       if (Args[ARG_PLAYCDDA]) {
  245.         len = strlen((char *) (Args[ARG_PLAYCDDA]));
  246.  
  247.         if (len >= sizeof (g_play_cdda_command)) {
  248.        Display_Error ("PLAYCDDA command name too long");
  249.        result = FALSE;
  250.         } else
  251.       strcpy (g_play_cdda_command, (char *) (Args[ARG_PLAYCDDA]));
  252.       } else
  253.         g_play_cdda_command[0] = 0;
  254.  
  255.       if (Args[ARG_XPOS])
  256.         g_xpos = *(long *) (Args[ARG_XPOS]);
  257.       if (Args[ARG_YPOS])
  258.         g_ypos = *(long *) (Args[ARG_YPOS]);
  259.  
  260.       FreeArgs(ArgsPtr);
  261.     } else {
  262.       Fault(IoErr (), (UBYTE *) "", LocalBuffer, sizeof (LocalBuffer));
  263.       Display_Error ("Error while parsing \"Startup\" field in Mountlist:\n%s",
  264.                    LocalBuffer + 2);
  265.     }
  266.  
  267.     FreeDosObject (DOS_RDARGS, ArgsPtr);
  268.   } else
  269.     Display_Error ("Out of memory");
  270.  
  271.   if (result) {
  272.     if (!(g_cd = Open_CDROM (g_device, g_unit, g_trackdisk, g_memory_type,
  273.                    g_std_buffers, g_file_buffers))) {
  274.       switch (g_cdrom_errno) {
  275.       case CDROMERR_NO_MEMORY:
  276.         Display_Error ("Out of memory: cannot allocate buffers\n"
  277.                "(Try CHIP, FAST, DMA or ANY option.)");
  278.         break;
  279.       case CDROMERR_MSGPORT:
  280.         Display_Error ("Cannot open the message port.");
  281.         break;
  282.       case CDROMERR_IOREQ:
  283.         Display_Error ("Cannot open the I/O request structure.");
  284.         break;
  285.       case CDROMERR_DEVICE:
  286.         Display_Error ("Cannot open \"%s\" unit %ld", g_device, (int) g_unit);
  287.         break;
  288.       case CDROMERR_BLOCKSIZE:
  289.         Display_Error ("Cannot access CDROM drive: illegal blocksize.");
  290.     break;
  291.       default:
  292.         break;
  293.       }
  294.       result = FALSE;
  295.     }
  296.   }
  297.  
  298.   return result;
  299. }
  300.  
  301. int Handle_Control_Packet (ULONG p_type, ULONG p_par1, ULONG p_par2)
  302. {
  303.   switch (p_type) {
  304.   case CDCMD_LOWERCASE:
  305.     g_map_to_lowercase = p_par1;
  306.     break;
  307.   case CDCMD_MACTOISO:
  308.     g_convert_hfs_filenames = p_par1;
  309.     break;
  310.   case CDCMD_CONVERTSPACES:
  311.     g_convert_hfs_spaces = p_par1;
  312.     break;
  313.   case CDCMD_SHOWVERSION:
  314.     g_show_version_numbers = p_par1;
  315.     break;
  316.   case CDCMD_HFSFIRST:
  317.     g_hfs_first = p_par1;
  318.     break;
  319.   case CDCMD_DATAEXT:
  320.     strcpy (g_data_fork_extension, (char *) p_par1);
  321.     break;
  322.   case CDCMD_RESOURCEEXT:
  323.     strcpy (g_resource_fork_extension, (char *) p_par1);
  324.     break;
  325.   default:
  326.     return 999;
  327.   }
  328.   return 0;
  329. }
  330.  
  331. #ifdef _DCC
  332. extern void debugproc (void);
  333. #if defined(NDEBUG) && !defined(DEBUG_SECTORS)
  334. void debugmain (void) {;}
  335. #endif
  336. #endif
  337.  
  338. #if !defined(NDEBUG) || defined(DEBUG_SECTORS)
  339.  
  340. char *typetostr (int ty)
  341. {
  342.     switch(ty) {
  343.     case ACTION_DIE:        return("DIE");
  344.     case ACTION_FINDUPDATE:     return("OPEN-RW");
  345.     case ACTION_FINDINPUT:    return("OPEN-OLD");
  346.     case ACTION_FINDOUTPUT:    return("OPEN-NEW");
  347.     case ACTION_READ:        return("READ");
  348.     case ACTION_WRITE:        return("WRITE");
  349.     case ACTION_END:        return("CLOSE");
  350.     case ACTION_SEEK:        return("SEEK");
  351.     case ACTION_EXAMINE_NEXT:    return("EXAMINE NEXT");
  352.     case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
  353.     case ACTION_INFO:        return("INFO");
  354.     case ACTION_DISK_INFO:    return("DISK INFO");
  355.     case ACTION_PARENT:     return("PARENTDIR");
  356.     case ACTION_DELETE_OBJECT:    return("DELETE");
  357.     case ACTION_CREATE_DIR:    return("CREATEDIR");
  358.     case ACTION_LOCATE_OBJECT:    return("LOCK");
  359.     case ACTION_COPY_DIR:    return("DUPLOCK");
  360.     case ACTION_FREE_LOCK:    return("FREELOCK");
  361.     case ACTION_SET_PROTECT:    return("SETPROTECT");
  362.     case ACTION_SET_COMMENT:    return("SETCOMMENT");
  363.     case ACTION_RENAME_OBJECT:    return("RENAME");
  364.     case ACTION_INHIBIT:    return("INHIBIT");
  365.     case ACTION_RENAME_DISK:    return("RENAME DISK");
  366.     case ACTION_MORE_CACHE:    return("MORE CACHE");
  367.     case ACTION_WAIT_CHAR:    return("WAIT FOR CHAR");
  368.     case ACTION_FLUSH:        return("FLUSH");
  369.     case ACTION_SCREEN_MODE:    return("SCREENMODE");
  370.     case ACTION_IS_FILESYSTEM:    return("IS_FILESYSTEM");
  371.     case ACTION_SAME_LOCK:      return("SAME_LOCK");
  372.     case ACTION_COPY_DIR_FH:    return("COPY_DIR_FH");
  373.     case ACTION_PARENT_FH:      return("PARENT_FH");
  374.     case ACTION_EXAMINE_FH:     return("EXAMINE_FH");
  375.     case ACTION_FH_FROM_LOCK:   return("FH_FROM_LOCK");
  376.     case ACTION_CURRENT_VOLUME: return("CURRENT_VOLUME");
  377.     case ACTION_READ_LINK:    return("READ LINK");
  378.     case ACTION_USER:        return("USER");
  379.     default:            return("---------UNKNOWN-------");
  380.     }
  381. }
  382.  
  383. /*
  384.  *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  385.  *  devices from within a DOS device driver because they use the same
  386.  *  message port as the driver.  If you need to make such calls you must
  387.  *  create a port and construct the DOS messages yourself.  I do not
  388.  *  do this.  To get debugging info out another PROCESS is created to which
  389.  *  debugging messages can be sent.
  390.  *
  391.  *  You want the priority of the debug process to be larger than the
  392.  *  priority of your DOS handler.  This is so if your DOS handler crashes
  393.  *  you have a better idea of where it died from the debugging messages
  394.  *  (remember that the two processes are asyncronous from each other).
  395.  */
  396.  
  397. /*
  398.  *  BTW, the DOS library used by debugmain() was actually opened by
  399.  *  the device driver.    Note: DummyMsg cannot be on debugmain()'s stack
  400.  *  since debugmain() goes away on the final handshake.
  401.  */
  402.  
  403. #ifdef LATTICE
  404. void __saveds debugmain (void)
  405. #else
  406. void debugmain (void)
  407. #endif    /* LATTICE */
  408. {
  409.     MSG *msg;
  410.     short len;
  411.     void *fh;
  412. #ifdef LOG_MESSAGES
  413.     void *out;
  414. #endif
  415.  
  416. #ifdef AZTEC_C
  417.     extern void geta4 (void);
  418.  
  419.     geta4();
  420. #endif
  421.  
  422.     Dbport = CreateMsgPort ();
  423.     fh = (void *) Open ((UBYTE *) "con:0/0/640/100/debugwindow", 1006);
  424.     PutMsg(Dback, &DummyMsg);
  425. #ifdef LOG_MESSAGES
  426. #ifdef LOG_TO_PAR
  427.     out = (void *) Open ((UBYTE *) "PAR:", 1006);
  428. #else
  429.     out = (void *) Open ((UBYTE *) "ram:cd.log", 1006);
  430. #endif
  431. #endif
  432.     for (;;) {
  433.     WaitPort(Dbport);
  434.     msg = GetMsg(Dbport);
  435.     len = msg->mn_Length;
  436.     if (len == 0)
  437.         break;
  438.     --len;                  /*  Fix length up   */
  439.     Write((BPTR) fh, msg+1, len);
  440. #ifdef LOG_MESSAGES
  441.     Write((BPTR) out, msg+1, len);
  442. #endif
  443.     FreeMem(msg,sizeof(MSG)+len+1);
  444.     }
  445.     Close ((BPTR) fh);
  446. #ifdef LOG_MESSAGES
  447.     Close ((BPTR) out);
  448. #endif
  449.     DeleteMsgPort(Dbport);
  450.     PutMsg(Dback,&DummyMsg);          /*  Kill handshake  */
  451. }
  452.  
  453. void dbinit (void)
  454. {
  455.     TASK *task = FindTask(NULL);
  456.  
  457.     Dback = CreateMsgPort();
  458.     if (CreateNewProcTags (
  459. #ifdef _DCC
  460.                NP_Seglist, (BPTR) (CTOB(debugproc)),
  461. #else
  462.                NP_Entry, debugmain,
  463. #endif
  464.                    NP_Name, "DEV_DB",
  465.                       NP_Priority, task->tc_Node.ln_Pri+1,
  466.                       NP_StackSize, 4096,
  467.                       TAG_DONE)) {
  468.       WaitPort(Dback);                    /* handshake startup    */
  469.       GetMsg(Dback);                    /* remove dummy msg     */
  470.       dbprintf("Debugger running: %s, %s\n", TheVersion+6, __TIME__);
  471.     };
  472. }
  473.  
  474. void dbuninit (void)
  475. {
  476.     MSG killmsg;
  477.  
  478.     if (Dbport) {
  479.     killmsg.mn_Length = 0;        /*    0 means die        */
  480.     PutMsg(Dbport,&killmsg);
  481.     WaitPort(Dback);        /*    He's dead jim!      */
  482.     GetMsg(Dback);
  483.     DeleteMsgPort(Dback);
  484.  
  485.     /*
  486.      *  Since the debug process is running at a greater priority, I
  487.      *  am pretty sure that it is guarenteed to be completely removed
  488.      *  before this task gets control again.  Still, it doesn't hurt...
  489.      */
  490.  
  491.     Delay(100);            /*    ensure he's dead    */
  492.     }
  493. }
  494.  
  495. void dbprintf (char *format, ...)
  496. {
  497.     va_list arg;
  498.     char buf[256];
  499.     MSG *msg;
  500.  
  501.     va_start (arg, format);
  502.     if (Dbport && !DBDisable) {
  503.     vsprintf (buf, format, arg);
  504.     msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
  505.     msg->mn_Length = strlen(buf)+1;     /*    Length NEVER 0    */
  506.     strcpy((char *) (msg+1), buf);
  507.     PutMsg(Dbport,msg);
  508.     }
  509.     va_end (arg);
  510. }
  511.  
  512. #endif /* !NDEBUG || DEBUG_SECTORS */
  513.